﻿#pragma once
#include "XyNet/Common/Id.h"
#include "XyNet/Common/Singleton.h"

#if !defined(XYNET_PLATFORM_APPLE) && !defined(XYNET_PLATFORM_ANDROID)
#	define XYNET_USE_BOOST_LOG
#	include <boost/log/sinks.hpp>
#endif

namespace XyNet
{
	/// 日志
	class XYNET_API Logger : public DefaultObject<Logger>
	{
#ifdef XYNET_USE_BOOST_LOG
		typedef boost::log::sinks::text_file_backend BackendType;
		typedef boost::log::sinks::synchronous_sink<BackendType> SinkType;
#endif

	public:
		/// 严重等级
		enum SeverityLevel
		{
			Trace,
			Debug,
			Info,
			Warning,
			Error,
			Fatal
		};

	public:
		Logger();

		/// 设置基础文件名
		/// baseFileName不带扩展名，会根据baseFileName和rotation生成最终文件名（会重新记录文件）
		void setBaseFileName(const string& baseFileName, bool rotation = false);

		/// 设置严重等级，只输出高于设定等级的日志
		void setSeverityLevel(SeverityLevel level = Info);

		/// 获取是否写入控制台
		bool getWriteToConsole() const;
		/// 设置是否写入控制台
		void setWriteToConsole(bool setting);

		/// 记录日志
		void log(const string& message, SeverityLevel level = Info);

		/// 记录日志
		void logTrace(const string& message);
		/// 记录日志
		void logDebug(const string& message);
		/// 记录日志
		void logInfo(const string& message);
		/// 记录日志
		void logWarning(const string& message);
		/// 记录日志
		void logError(const string& message);
		/// 记录日志
		void logFatal(const string& message);

	private:
		/// 创建文件槽
		void createFileSink();
		/// 销毁文件槽
		void destoryFileSink();

		/// 获取严重等级字符串
		string getSeverityLevelString(SeverityLevel level) const;

	private:
#ifdef XYNET_USE_BOOST_LOG
		/// 后端
		boost::shared_ptr<BackendType> _backend;
		/// 文件槽
		boost::shared_ptr<SinkType> _sink;
#else
		boost::filesystem::ofstream _fileStream;
#endif

		/// 通道id，区分不同日志
		Id _channelId;
		/// 基础文件名
		string _baseFileName;
		/// 是否旋转格式文件
		bool _rotation;
		/// 严重等级
		SeverityLevel _severityLevel;

		/// 是否写入控制台
		bool _writeToConsole;

		/// id发生器，用于区分不同的日志类，必须是静态
		static IdGenerator _idGenerator;
	};
}